1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 // generated automatically - do not change 21 // find conversion definition on APILookup.txt 22 // implement new conversion functionalities on the wrap.utils pakage 23 24 25 module gtk.ListBox; 26 27 private import gio.ListModelIF; 28 private import glib.ConstructionException; 29 private import glib.ListG; 30 private import gobject.ObjectG; 31 private import gobject.Signals; 32 private import gtk.Adjustment; 33 private import gtk.ListBoxRow; 34 private import gtk.Widget; 35 private import gtk.c.functions; 36 public import gtk.c.types; 37 private import std.algorithm; 38 39 40 /** 41 * `GtkListBox` is a vertical list. 42 * 43 * A `GtkListBox` only contains `GtkListBoxRow` children. These rows can 44 * by dynamically sorted and filtered, and headers can be added dynamically 45 * depending on the row content. It also allows keyboard and mouse navigation 46 * and selection like a typical list. 47 * 48 * Using `GtkListBox` is often an alternative to `GtkTreeView`, especially 49 * when the list contents has a more complicated layout than what is allowed 50 * by a `GtkCellRenderer`, or when the contents is interactive (i.e. has a 51 * button in it). 52 * 53 * Although a `GtkListBox` must have only `GtkListBoxRow` children, you can 54 * add any kind of widget to it via [method@Gtk.ListBox.prepend], 55 * [method@Gtk.ListBox.append] and [method@Gtk.ListBox.insert] and a 56 * `GtkListBoxRow` widget will automatically be inserted between the list 57 * and the widget. 58 * 59 * `GtkListBoxRows` can be marked as activatable or selectable. If a row is 60 * activatable, [signal@Gtk.ListBox::row-activated] will be emitted for it when 61 * the user tries to activate it. If it is selectable, the row will be marked 62 * as selected when the user tries to select it. 63 * 64 * # GtkListBox as GtkBuildable 65 * 66 * The `GtkListBox` implementation of the `GtkBuildable` interface supports 67 * setting a child as the placeholder by specifying “placeholder” as the “type” 68 * attribute of a <child> element. See [method@Gtk.ListBox.set_placeholder] 69 * for info. 70 * 71 * # CSS nodes 72 * 73 * |[<!-- language="plain" --> 74 * list[.separators][.rich-list][.navigation-sidebar] 75 * ╰── row[.activatable] 76 * ]| 77 * 78 * `GtkListBox` uses a single CSS node named list. It may carry the .separators 79 * style class, when the [property@Gtk.ListBox:show-separators] property is set. 80 * Each `GtkListBoxRow` uses a single CSS node named row. The row nodes get the 81 * .activatable style class added when appropriate. 82 * 83 * The main list node may also carry style classes to select 84 * the style of [list presentation](section-list-widget.html#list-styles): 85 * .rich-list, .navigation-sidebar or .data-table. 86 * 87 * # Accessibility 88 * 89 * `GtkListBox` uses the %GTK_ACCESSIBLE_ROLE_LIST role and `GtkListBoxRow` uses 90 * the %GTK_ACCESSIBLE_ROLE_LIST_ITEM role. 91 */ 92 public class ListBox : Widget 93 { 94 /** the main Gtk struct */ 95 protected GtkListBox* gtkListBox; 96 97 /** Get the main Gtk struct */ 98 public GtkListBox* getListBoxStruct(bool transferOwnership = false) 99 { 100 if (transferOwnership) 101 ownedRef = false; 102 return gtkListBox; 103 } 104 105 /** the main Gtk struct as a void* */ 106 protected override void* getStruct() 107 { 108 return cast(void*)gtkListBox; 109 } 110 111 /** 112 * Sets our main struct and passes it to the parent class. 113 */ 114 public this (GtkListBox* gtkListBox, bool ownedRef = false) 115 { 116 this.gtkListBox = gtkListBox; 117 super(cast(GtkWidget*)gtkListBox, ownedRef); 118 } 119 120 121 /** */ 122 public static GType getType() 123 { 124 return gtk_list_box_get_type(); 125 } 126 127 /** 128 * Creates a new `GtkListBox` container. 129 * 130 * Returns: a new `GtkListBox` 131 * 132 * Throws: ConstructionException GTK+ fails to create the object. 133 */ 134 public this() 135 { 136 auto __p = gtk_list_box_new(); 137 138 if(__p is null) 139 { 140 throw new ConstructionException("null returned by new"); 141 } 142 143 this(cast(GtkListBox*) __p); 144 } 145 146 /** 147 * Append a widget to the list. 148 * 149 * If a sort function is set, the widget will 150 * actually be inserted at the calculated position. 151 * 152 * Params: 153 * child = the `GtkWidget` to add 154 */ 155 public void append(Widget child) 156 { 157 gtk_list_box_append(gtkListBox, (child is null) ? null : child.getWidgetStruct()); 158 } 159 160 /** 161 * Binds @model to @box. 162 * 163 * If @box was already bound to a model, that previous binding is 164 * destroyed. 165 * 166 * The contents of @box are cleared and then filled with widgets that 167 * represent items from @model. @box is updated whenever @model changes. 168 * If @model is %NULL, @box is left empty. 169 * 170 * It is undefined to add or remove widgets directly (for example, with 171 * [method@Gtk.ListBox.insert]) while @box is bound to a model. 172 * 173 * Note that using a model is incompatible with the filtering and sorting 174 * functionality in `GtkListBox`. When using a model, filtering and sorting 175 * should be implemented by the model. 176 * 177 * Params: 178 * model = the `GListModel` to be bound to @box 179 * createWidgetFunc = a function that creates widgets for items 180 * or %NULL in case you also passed %NULL as @model 181 * userData = user data passed to @create_widget_func 182 * userDataFreeFunc = function for freeing @user_data 183 */ 184 public void bindModel(ListModelIF model, GtkListBoxCreateWidgetFunc createWidgetFunc, void* userData, GDestroyNotify userDataFreeFunc) 185 { 186 gtk_list_box_bind_model(gtkListBox, (model is null) ? null : model.getListModelStruct(), createWidgetFunc, userData, userDataFreeFunc); 187 } 188 189 /** 190 * Add a drag highlight to a row. 191 * 192 * This is a helper function for implementing DnD onto a `GtkListBox`. 193 * The passed in @row will be highlighted by setting the 194 * %GTK_STATE_FLAG_DROP_ACTIVE state and any previously highlighted 195 * row will be unhighlighted. 196 * 197 * The row will also be unhighlighted when the widget gets 198 * a drag leave event. 199 * 200 * Params: 201 * row = a `GtkListBoxRow` 202 */ 203 public void dragHighlightRow(ListBoxRow row) 204 { 205 gtk_list_box_drag_highlight_row(gtkListBox, (row is null) ? null : row.getListBoxRowStruct()); 206 } 207 208 /** 209 * If a row has previously been highlighted via gtk_list_box_drag_highlight_row(), 210 * it will have the highlight removed. 211 */ 212 public void dragUnhighlightRow() 213 { 214 gtk_list_box_drag_unhighlight_row(gtkListBox); 215 } 216 217 /** 218 * Returns whether rows activate on single clicks. 219 * 220 * Returns: %TRUE if rows are activated on single click, %FALSE otherwise 221 */ 222 public bool getActivateOnSingleClick() 223 { 224 return gtk_list_box_get_activate_on_single_click(gtkListBox) != 0; 225 } 226 227 /** 228 * Gets the adjustment (if any) that the widget uses to 229 * for vertical scrolling. 230 * 231 * Returns: the adjustment 232 */ 233 public Adjustment getAdjustment() 234 { 235 auto __p = gtk_list_box_get_adjustment(gtkListBox); 236 237 if(__p is null) 238 { 239 return null; 240 } 241 242 return ObjectG.getDObject!(Adjustment)(cast(GtkAdjustment*) __p); 243 } 244 245 /** 246 * Gets the n-th child in the list (not counting headers). 247 * 248 * If @index_ is negative or larger than the number of items in the 249 * list, %NULL is returned. 250 * 251 * Params: 252 * index = the index of the row 253 * 254 * Returns: the child `GtkWidget` 255 */ 256 public ListBoxRow getRowAtIndex(int index) 257 { 258 auto __p = gtk_list_box_get_row_at_index(gtkListBox, index); 259 260 if(__p is null) 261 { 262 return null; 263 } 264 265 return ObjectG.getDObject!(ListBoxRow)(cast(GtkListBoxRow*) __p); 266 } 267 268 /** 269 * Gets the row at the @y position. 270 * 271 * Params: 272 * y = position 273 * 274 * Returns: the row 275 */ 276 public ListBoxRow getRowAtY(int y) 277 { 278 auto __p = gtk_list_box_get_row_at_y(gtkListBox, y); 279 280 if(__p is null) 281 { 282 return null; 283 } 284 285 return ObjectG.getDObject!(ListBoxRow)(cast(GtkListBoxRow*) __p); 286 } 287 288 /** 289 * Gets the selected row, or %NULL if no rows are selected. 290 * 291 * Note that the box may allow multiple selection, in which 292 * case you should use [method@Gtk.ListBox.selected_foreach] to 293 * find all selected rows. 294 * 295 * Returns: the selected row 296 */ 297 public ListBoxRow getSelectedRow() 298 { 299 auto __p = gtk_list_box_get_selected_row(gtkListBox); 300 301 if(__p is null) 302 { 303 return null; 304 } 305 306 return ObjectG.getDObject!(ListBoxRow)(cast(GtkListBoxRow*) __p); 307 } 308 309 /** 310 * Creates a list of all selected children. 311 * 312 * Returns: A `GList` containing the `GtkWidget` for each selected child. 313 * Free with g_list_free() when done. 314 */ 315 public ListG getSelectedRows() 316 { 317 auto __p = gtk_list_box_get_selected_rows(gtkListBox); 318 319 if(__p is null) 320 { 321 return null; 322 } 323 324 return new ListG(cast(GList*) __p); 325 } 326 327 /** 328 * Gets the selection mode of the listbox. 329 * 330 * Returns: a `GtkSelectionMode` 331 */ 332 public GtkSelectionMode getSelectionMode() 333 { 334 return gtk_list_box_get_selection_mode(gtkListBox); 335 } 336 337 /** 338 * Returns whether the list box should show separators 339 * between rows. 340 * 341 * Returns: %TRUE if the list box shows separators 342 */ 343 public bool getShowSeparators() 344 { 345 return gtk_list_box_get_show_separators(gtkListBox) != 0; 346 } 347 348 /** 349 * Insert the @child into the @box at @position. 350 * 351 * If a sort function is 352 * set, the widget will actually be inserted at the calculated position. 353 * 354 * If @position is -1, or larger than the total number of items in the 355 * @box, then the @child will be appended to the end. 356 * 357 * Params: 358 * child = the `GtkWidget` to add 359 * position = the position to insert @child in 360 */ 361 public void insert(Widget child, int position) 362 { 363 gtk_list_box_insert(gtkListBox, (child is null) ? null : child.getWidgetStruct(), position); 364 } 365 366 /** 367 * Update the filtering for all rows. 368 * 369 * Call this when result 370 * of the filter function on the @box is changed due 371 * to an external factor. For instance, this would be used 372 * if the filter function just looked for a specific search 373 * string and the entry with the search string has changed. 374 */ 375 public void invalidateFilter() 376 { 377 gtk_list_box_invalidate_filter(gtkListBox); 378 } 379 380 /** 381 * Update the separators for all rows. 382 * 383 * Call this when result 384 * of the header function on the @box is changed due 385 * to an external factor. 386 */ 387 public void invalidateHeaders() 388 { 389 gtk_list_box_invalidate_headers(gtkListBox); 390 } 391 392 /** 393 * Update the sorting for all rows. 394 * 395 * Call this when result 396 * of the sort function on the @box is changed due 397 * to an external factor. 398 */ 399 public void invalidateSort() 400 { 401 gtk_list_box_invalidate_sort(gtkListBox); 402 } 403 404 /** 405 * Prepend a widget to the list. 406 * 407 * If a sort function is set, the widget will 408 * actually be inserted at the calculated position. 409 * 410 * Params: 411 * child = the `GtkWidget` to add 412 */ 413 public void prepend(Widget child) 414 { 415 gtk_list_box_prepend(gtkListBox, (child is null) ? null : child.getWidgetStruct()); 416 } 417 418 /** 419 * Removes a child from @box. 420 * 421 * Params: 422 * child = the child to remove 423 */ 424 public void remove(Widget child) 425 { 426 gtk_list_box_remove(gtkListBox, (child is null) ? null : child.getWidgetStruct()); 427 } 428 429 /** 430 * Select all children of @box, if the selection mode allows it. 431 */ 432 public void selectAll() 433 { 434 gtk_list_box_select_all(gtkListBox); 435 } 436 437 /** 438 * Make @row the currently selected row. 439 * 440 * Params: 441 * row = The row to select 442 */ 443 public void selectRow(ListBoxRow row) 444 { 445 gtk_list_box_select_row(gtkListBox, (row is null) ? null : row.getListBoxRowStruct()); 446 } 447 448 /** 449 * Calls a function for each selected child. 450 * 451 * Note that the selection cannot be modified from within this function. 452 * 453 * Params: 454 * func = the function to call for each selected child 455 * data = user data to pass to the function 456 */ 457 public void selectedForeach(GtkListBoxForeachFunc func, void* data) 458 { 459 gtk_list_box_selected_foreach(gtkListBox, func, data); 460 } 461 462 /** 463 * If @single is %TRUE, rows will be activated when you click on them, 464 * otherwise you need to double-click. 465 * 466 * Params: 467 * single = a boolean 468 */ 469 public void setActivateOnSingleClick(bool single) 470 { 471 gtk_list_box_set_activate_on_single_click(gtkListBox, single); 472 } 473 474 /** 475 * Sets the adjustment (if any) that the widget uses to 476 * for vertical scrolling. 477 * 478 * For instance, this is used to get the page size for 479 * PageUp/Down key handling. 480 * 481 * In the normal case when the @box is packed inside 482 * a `GtkScrolledWindow` the adjustment from that will 483 * be picked up automatically, so there is no need 484 * to manually do that. 485 * 486 * Params: 487 * adjustment = the adjustment 488 */ 489 public void setAdjustment(Adjustment adjustment) 490 { 491 gtk_list_box_set_adjustment(gtkListBox, (adjustment is null) ? null : adjustment.getAdjustmentStruct()); 492 } 493 494 /** 495 * By setting a filter function on the @box one can decide dynamically which 496 * of the rows to show. 497 * 498 * For instance, to implement a search function on a list that 499 * filters the original list to only show the matching rows. 500 * 501 * The @filter_func will be called for each row after the call, and 502 * it will continue to be called each time a row changes (via 503 * [method@Gtk.ListBoxRow.changed]) or when [method@Gtk.ListBox.invalidate_filter] 504 * is called. 505 * 506 * Note that using a filter function is incompatible with using a model 507 * (see [method@Gtk.ListBox.bind_model]). 508 * 509 * Params: 510 * filterFunc = callback that lets you filter which rows to show 511 * userData = user data passed to @filter_func 512 * destroy = destroy notifier for @user_data 513 */ 514 public void setFilterFunc(GtkListBoxFilterFunc filterFunc, void* userData, GDestroyNotify destroy) 515 { 516 gtk_list_box_set_filter_func(gtkListBox, filterFunc, userData, destroy); 517 } 518 519 /** 520 * Sets a header function. 521 * 522 * By setting a header function on the @box one can dynamically add headers 523 * in front of rows, depending on the contents of the row and its position 524 * in the list. 525 * 526 * For instance, one could use it to add headers in front of the first item 527 * of a new kind, in a list sorted by the kind. 528 * 529 * The @update_header can look at the current header widget using 530 * [method@Gtk.ListBoxRow.get_header] and either update the state of the widget 531 * as needed, or set a new one using [method@Gtk.ListBoxRow.set_header]. If no 532 * header is needed, set the header to %NULL. 533 * 534 * Note that you may get many calls @update_header to this for a particular 535 * row when e.g. changing things that don’t affect the header. In this case 536 * it is important for performance to not blindly replace an existing header 537 * with an identical one. 538 * 539 * The @update_header function will be called for each row after the call, 540 * and it will continue to be called each time a row changes (via 541 * [method@Gtk.ListBoxRow.changed]) and when the row before changes (either 542 * by [method@Gtk.ListBoxRow.changed] on the previous row, or when the previous 543 * row becomes a different row). It is also called for all rows when 544 * [method@Gtk.ListBox.invalidate_headers] is called. 545 * 546 * Params: 547 * updateHeader = callback that lets you add row headers 548 * userData = user data passed to @update_header 549 * destroy = destroy notifier for @user_data 550 */ 551 public void setHeaderFunc(GtkListBoxUpdateHeaderFunc updateHeader, void* userData, GDestroyNotify destroy) 552 { 553 gtk_list_box_set_header_func(gtkListBox, updateHeader, userData, destroy); 554 } 555 556 /** 557 * Sets the placeholder widget that is shown in the list when 558 * it doesn't display any visible children. 559 * 560 * Params: 561 * placeholder = a `GtkWidget` 562 */ 563 public void setPlaceholder(Widget placeholder) 564 { 565 gtk_list_box_set_placeholder(gtkListBox, (placeholder is null) ? null : placeholder.getWidgetStruct()); 566 } 567 568 /** 569 * Sets how selection works in the listbox. 570 * 571 * Params: 572 * mode = The `GtkSelectionMode` 573 */ 574 public void setSelectionMode(GtkSelectionMode mode) 575 { 576 gtk_list_box_set_selection_mode(gtkListBox, mode); 577 } 578 579 /** 580 * Sets whether the list box should show separators 581 * between rows. 582 * 583 * Params: 584 * showSeparators = %TRUE to show separators 585 */ 586 public void setShowSeparators(bool showSeparators) 587 { 588 gtk_list_box_set_show_separators(gtkListBox, showSeparators); 589 } 590 591 /** 592 * Sets a sort function. 593 * 594 * By setting a sort function on the @box one can dynamically reorder 595 * the rows of the list, based on the contents of the rows. 596 * 597 * The @sort_func will be called for each row after the call, and will 598 * continue to be called each time a row changes (via 599 * [method@Gtk.ListBoxRow.changed]) and when [method@Gtk.ListBox.invalidate_sort] 600 * is called. 601 * 602 * Note that using a sort function is incompatible with using a model 603 * (see [method@Gtk.ListBox.bind_model]). 604 * 605 * Params: 606 * sortFunc = the sort function 607 * userData = user data passed to @sort_func 608 * destroy = destroy notifier for @user_data 609 */ 610 public void setSortFunc(GtkListBoxSortFunc sortFunc, void* userData, GDestroyNotify destroy) 611 { 612 gtk_list_box_set_sort_func(gtkListBox, sortFunc, userData, destroy); 613 } 614 615 /** 616 * Unselect all children of @box, if the selection mode allows it. 617 */ 618 public void unselectAll() 619 { 620 gtk_list_box_unselect_all(gtkListBox); 621 } 622 623 /** 624 * Unselects a single row of @box, if the selection mode allows it. 625 * 626 * Params: 627 * row = the row to unselected 628 */ 629 public void unselectRow(ListBoxRow row) 630 { 631 gtk_list_box_unselect_row(gtkListBox, (row is null) ? null : row.getListBoxRowStruct()); 632 } 633 634 /** */ 635 gulong addOnActivateCursorRow(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 636 { 637 return Signals.connect(this, "activate-cursor-row", dlg, connectFlags ^ ConnectFlags.SWAPPED); 638 } 639 640 /** */ 641 gulong addOnMoveCursor(void delegate(GtkMovementStep, int, bool, bool, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 642 { 643 return Signals.connect(this, "move-cursor", dlg, connectFlags ^ ConnectFlags.SWAPPED); 644 } 645 646 /** 647 * Emitted when a row has been activated by the user. 648 * 649 * Params: 650 * row = the activated row 651 */ 652 gulong addOnRowActivated(void delegate(ListBoxRow, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 653 { 654 return Signals.connect(this, "row-activated", dlg, connectFlags ^ ConnectFlags.SWAPPED); 655 } 656 657 /** 658 * Emitted when a new row is selected, or (with a %NULL @row) 659 * when the selection is cleared. 660 * 661 * When the @box is using %GTK_SELECTION_MULTIPLE, this signal will not 662 * give you the full picture of selection changes, and you should use 663 * the [signal@Gtk.ListBox::selected-rows-changed] signal instead. 664 * 665 * Params: 666 * row = the selected row 667 */ 668 gulong addOnRowSelected(void delegate(ListBoxRow, ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 669 { 670 return Signals.connect(this, "row-selected", dlg, connectFlags ^ ConnectFlags.SWAPPED); 671 } 672 673 /** 674 * Emitted to select all children of the box, if the selection 675 * mode permits it. 676 * 677 * This is a [keybinding signal](class.SignalAction.html). 678 * 679 * The default binding for this signal is <kbd>Ctrl</kbd>-<kbd>a</kbd>. 680 */ 681 gulong addOnSelectAll(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 682 { 683 return Signals.connect(this, "select-all", dlg, connectFlags ^ ConnectFlags.SWAPPED); 684 } 685 686 /** 687 * Emitted when the set of selected rows changes. 688 */ 689 gulong addOnSelectedRowsChanged(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 690 { 691 return Signals.connect(this, "selected-rows-changed", dlg, connectFlags ^ ConnectFlags.SWAPPED); 692 } 693 694 /** */ 695 gulong addOnToggleCursorRow(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 696 { 697 return Signals.connect(this, "toggle-cursor-row", dlg, connectFlags ^ ConnectFlags.SWAPPED); 698 } 699 700 /** 701 * Emitted to unselect all children of the box, if the selection 702 * mode permits it. 703 * 704 * This is a [keybinding signal](class.SignalAction.html). 705 * 706 * The default binding for this signal is 707 * <kbd>Ctrl</kbd>-<kbd>Shift</kbd>-<kbd>a</kbd>. 708 */ 709 gulong addOnUnselectAll(void delegate(ListBox) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0) 710 { 711 return Signals.connect(this, "unselect-all", dlg, connectFlags ^ ConnectFlags.SWAPPED); 712 } 713 }